package cn.madis.ymcc.service.impl;

import cn.madis.ymcc.doc.CourseDoc;
import cn.madis.ymcc.dto.Aggs;
import cn.madis.ymcc.dto.SearchEsDto;
import cn.madis.ymcc.esmapper.HighlightResultMapper;
import cn.madis.ymcc.repository.CourseElasticsearchRepository;
import cn.madis.ymcc.result.PageList;
import cn.madis.ymcc.service.ICourseSearchService;
import cn.madis.ymcc.utils.EsAggPageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;

import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CourseSearchServiceImpl implements ICourseSearchService {
    @Autowired
    private CourseElasticsearchRepository courseElasticsearchRepository;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;



    /*
    向es中加数据
     */
    @Override
    public void save(CourseDoc courseDoc) {
        courseElasticsearchRepository.save(courseDoc);
    }
    /*
    删除es中数据
     */
    @Override
    public void remove(Long courseId) {
        courseElasticsearchRepository.deleteById(courseId);
    }


    /*
    查询es中数据
     */
    @Override
    public PageList<CourseDoc> search(SearchEsDto searchEsDto) {

        //条件查询
        //分页查询
        //排序查询
        //高亮
        //聚合
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //分页查询----------------------------------------
        builder.withPageable(PageRequest.of(searchEsDto.getPage() - 1 ,searchEsDto.getRows()));
        //排序
        if (StringUtils.hasLength(searchEsDto.getSortField())){
            String sort ="";
            switch (searchEsDto.getSortField().toLowerCase()){
                case "xl" :  sort = "saleCount"; break;
                case "xp" :  sort = "onlineTime"; break;
                case "pl" :  sort = "commentCount"; break;
                case "jg" :  sort = "price"; break;
                case "rq" :  sort = "viewCount"; break;
            }
            if (StringUtils.hasLength(sort)){
                SortOrder asc = SortOrder.ASC;
                if (StringUtils.hasLength(searchEsDto.getSortType())){
                   asc = searchEsDto.getSortType().toUpperCase().equals("ASC") ? SortOrder.ASC: SortOrder.DESC;
                }
                builder.withSort(SortBuilders.fieldSort(sort).order(asc));
            }
        }
        //  keyword;
        // courseTypeId;
        // gradeName;
        //private BigDecimal priceMin;
        //private BigDecimal priceMax;
        //条件查询  根据前端传过来的字段去es中查
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(searchEsDto.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("name",searchEsDto.getKeyword()));
        }

        if (searchEsDto.getCourseTypeId() != null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId",searchEsDto.getCourseTypeId()));
        }

        if (StringUtils.hasLength(searchEsDto.getGradeName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName",searchEsDto.getGradeName()));
        }

        if (searchEsDto.getPriceMin() != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(searchEsDto.getPriceMin()));
        }

        if (searchEsDto.getPriceMax() != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(searchEsDto.getPriceMax()));
        }

        //处理高亮
        builder.withHighlightFields(
                new HighlightBuilder.Field("name")
                        .preTags("<font style='color:blue'>")
                        .postTags("</font>")
        );

        //聚合
        builder.addAggregation(AggregationBuilders.terms("gradeNameAgg").field("gradeName"));

        //查询--------------------------------------------
        builder.withQuery(boolQueryBuilder);
        NativeSearchQuery build = builder.build();
       // Page<CourseDoc> page = courseElasticsearchRepository.search(build);
        //处理高亮结果
        AggregatedPage<CourseDoc> page = elasticsearchRestTemplate.queryForPage(build, CourseDoc.class, highlightResultMapper);
        //处理聚合结果
        //拿到所有聚合结果
        Aggregations aggregations = page.getAggregations();
        Map<String, Aggregation> stringAggregationMap = aggregations.asMap();

        //转儿子接受
        ParsedStringTerms gradeNameAgg = (ParsedStringTerms)stringAggregationMap.get("gradeNameAgg");
        HashMap<String, List<Aggs>> map = new HashMap<>();
        List<Aggs> collect = gradeNameAgg.getBuckets().stream()
               .map(bucket -> new Aggs(bucket.getKeyAsString(), bucket.getDocCount())).collect(Collectors.toList());



       map.put("gradeNameAgg",collect);



        return new EsAggPageList(page.getTotalElements(),page.getContent(),map);
    }
}
